//
//  XLHttpRequest.m
//  MPTinyAppLearn
//
//  Created by xl on 2019/11/7.
//  Copyright © 2019 xl. All rights reserved.
//

#import "XLHttpRequest.h"
#import "XLNetworking.h"
#import "XLRequestManager.h"
#import "UIDevice+XL.h"
#import "XLDateTool.h"
#import "XLUserDefaults.h"
#import <AFURLResponseSerialization.h>

@interface XLHttpRequest()

@property (nonatomic, copy) XLResponseSuccessBlock successBlock;
@property (nonatomic, copy) XLResponseFailBlock failBlock;



@end

@implementation XLHttpRequest

- (void)requestWithMethod:(XLHttpMedthType)method
                      url:(NSString *)url
                   params:(NSDictionary *)params
            isExtraParams:(BOOL)isExtraParams
             successBlock:(XLResponseSuccessBlock)successBlock
                failBlock:(XLResponseFailBlock)failBlock {
    self.successBlock = successBlock;
    self.failBlock = failBlock;
    
    //对网络封装 发送请求
    NSString *requestUrl = [[self currentBaseurl] stringByAppendingString:url];
    
    NSDictionary *dict = params;
    if (isExtraParams) {
        dict = [self checkExtraDeviceParametersInDic:params];
    }
    //判断当前是否设置过滤当前请求
    if ([self currentIsFiletr] && [[XLRequestManager sharedInstance] filterRequest:requestUrl]) {//如果任务队列中有当前请求，则直接返回。
        return;
    }
    [XLNetworking configTimeout:[self currentTimeOut]];
    int requestId = [[XLRequestManager sharedInstance] getNextReqId];
    NSURLSessionTask *sessionTask;
    if (method == XLHttpMedthTypePOST) {
        sessionTask = [XLNetworking postWithUrl:requestUrl params:dict success:^(XLServerRequestsStatus status, XLNetworkReachabilityStatus reachability, id  _Nonnull response) {
            [[XLRequestManager sharedInstance] removeReqConfig:requestId];
            [self onSuccessStatus:status reachability:reachability response:response];
        } fail:^(XLServerRequestsStatus status, XLNetworkReachabilityStatus reachability, id  _Nonnull response, NSError * _Nonnull error) {
            [[XLRequestManager sharedInstance] removeReqConfig:requestId];
            [self onFailStatus:status reachability:reachability response:response error:error];
        }];
    } else{
        sessionTask = [XLNetworking getWithUrl:requestUrl params:dict success:^(XLServerRequestsStatus status, XLNetworkReachabilityStatus reachability, id  _Nonnull response) {
           [[XLRequestManager sharedInstance] removeReqConfig:requestId];
           [self onSuccessStatus:status reachability:reachability response:response];
        } fail:^(XLServerRequestsStatus status, XLNetworkReachabilityStatus reachability, id  _Nonnull response, NSError * _Nonnull error) {
            [[XLRequestManager sharedInstance] removeReqConfig:requestId];
            [self onFailStatus:status reachability:reachability response:response error:error];
        }];
    }
    XLRequestConfig *config = [XLRequestConfig new];
    config.reqId =requestId;
    config.baseUrl = requestUrl;
    config.requestTask = sessionTask;
    //增加一条请求记录
    [[XLRequestManager sharedInstance] addReqConfig:config];
   
}

- (void)requestWithMethod:(XLHttpMedthType)method
                      url:(NSString *)url
                   params:(NSDictionary *)params
             successBlock:(XLResponseSuccessBlock)successBlock
                failBlock:(XLResponseFailBlock)failBlock
            progressBlock:(XLProgressBlock)progressBlock {
    
}


- (void)requestWithMethod:(XLHttpMedthType)method
                      url:(NSString *)url
                   params:(NSDictionary *)params
                    image:(UIImage *)image
                 fileName:(NSString *)fileName
                     name:(NSString *)name
             successBlock:(XLResponseSuccessBlock)successBlock
                failBlock:(XLResponseFailBlock)failBlock
            progressBlock:(XLProgressBlock)progressBlock {
    
}

#pragma mark - Private
- (void)onSuccessStatus:(XLServerRequestsStatus)status
           reachability:(XLNetworkReachabilityStatus)reachability
               response:(id)response {
    id responseData = [self parseFormPesponseData:response];
    if ([responseData isKindOfClass:[NSDictionary class]]) {
        NSDictionary *rspDic = (NSDictionary *)responseData;
        int result = [[rspDic objectForKey:@"code"] intValue];
        if (result == 0) {
            if ([[rspDic objectForKey:@"data"] isKindOfClass:[NSNull class]]) {
                self.successBlock(nil);
            } else {
                self.successBlock(rspDic);
            }
        } else if (result == 401) {
            NSError *error = nil;
            self.failBlock(status, reachability, error, rspDic);
            [XLNotif postNotificationName:XLNotificationTokenDisableFromServer object:@"401"];

        } else {
            //数据异常
            NSError *error = nil;
            self.failBlock(status, reachability, error, rspDic);
        }
        
        NSString *errorMessage = [response objectForKey:@"msg"];
        //存入服务器时间差
        NSNumber *networkTimestamp = [responseData objectForKey:@"timestamp"];
        if (!ISEmptyString(errorMessage) && result != 0) {
            [XLToast showErrorMessage:errorMessage];
        }
        if (!ISEmptyNumber(networkTimestamp)) {
            NSTimeInterval serverTime = [[responseData objectForKey:@"timestamp"] doubleValue];
            NSTimeInterval now = [XLDateTool currentTimeInMillisecondsWithServerSync:NO];
            NSTimeInterval diffTime = now - serverTime;
            [XLUserDefaults updateServerDiffTime:diffTime];
        }
    } else {
       //数据异常
        NSError *error = nil;
        self.failBlock(status, reachability, error, nil);
    }
}

- (void)onFailStatus:(XLServerRequestsStatus)status
        reachability:(XLNetworkReachabilityStatus)reachability
            response:(id)response error:(NSError *)error {
    if (error.code == NSURLErrorBadServerResponse) {
        NSDictionary *errorDic = error.userInfo;
        NSHTTPURLResponse *response = [errorDic objectForKey:AFNetworkingOperationFailingURLResponseErrorKey];
        if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
            //token 失效 重新登录
            NSInteger errorCode = response.statusCode;
            if (errorCode == XLNetworkTokenDisableCode) {
                [[XLRequestManager sharedInstance] removeAllRequest];
                NSData *errorData = errorDic[@"com.alamofire.serialization.response.error.data"];
                NSDictionary *errorDataDict = [NSJSONSerialization JSONObjectWithData:errorData options:NSJSONReadingMutableLeaves error:nil];
                NSLog(@"401请求后进一步查询响应体:%@",errorDataDict);
                NSArray *allKeys = [errorDataDict allKeys];
                if ([allKeys containsObject:@"code"]) {
                    NSString *serverCode = errorDataDict[@"code"];
                    [XLNotif postNotificationName:XLNotificationTokenDisableFromServer object:serverCode];
                }
            } else {
                [XLToast showErrorMessage:XLParamsErrorText];
            }
           
        } else {
            [XLToast showErrorMessage:XLNetErrorText];
        }
    } else if (error.code == NSURLErrorTimedOut) {
        [XLToast showErrorMessage:XLNetTimeOutText];
    } else {
        [XLToast showErrorMessage:XLNetErrorText];
    }
    self.failBlock(status, reachability, error, nil);
}

- (NSDictionary *)checkExtraDeviceParametersInDic:(NSDictionary *)oldDic
{
    NSMutableDictionary *dic = [[NSMutableDictionary alloc] initWithDictionary:oldDic];
    
    if (![oldDic objectForKey:@"appVersion"]) {
        NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
        // app版本
        NSString *appVersion = [infoDictionary objectForKey:@"CFBundleShortVersionString"];
        if (!ISEmptyString(appVersion)) {
            [dic setObject:appVersion forKey:@"appVersion"];
        }
    }
    
    if (![oldDic objectForKey:@"brand"]) {
        //机器类型：iPhone
        NSString * brand = [[UIDevice currentDevice] model];
        if (!ISEmptyString(brand)) {
            [dic setObject:brand forKey:@"brand"];
        }
    }
    
    //手机型号对应的手机名称
    if (![oldDic objectForKey:@"model"]) {
        NSString *model = [UIDevice currentDevice].machineType;
        if (!ISEmptyString(model)) {
            [dic setObject:model forKey:@"model"];
        }
    }

    if (![oldDic objectForKey:@"systemVersion"]) {
        //手机系统版本：11.1.2
        NSString* systemVersion = [[UIDevice currentDevice] systemVersion];
        if (!ISEmptyString(systemVersion)) {
            [dic setObject:systemVersion forKey:@"systemVersion"];
        }
    }

    //1、IOS ,2、安卓 ,3、其它
    if (![oldDic objectForKey:@"system"]) {
        [dic setObject:@(1) forKey:@"system"];
    }
    
    if (![oldDic objectForKey:@"uniqueId"]) {
        NSString *uuid = [UIDevice currentDevice].uuid;
        if (!ISEmptyString(uuid)) {
            [dic setObject:uuid forKey:@"uniqueId"];
        }
    }

    return dic;
}

- (NSString *)currentBaseurl {
    NSString *serverHttpDomain = XLServerHttpDomain;
    
    #ifdef DEBUG
    //测试模式才可以切换IP
    NSString *testHttpDomain = [XLStandardUserDefaults objectForKey:@"TestHttpDomain"];
    if (!ISEmptyString(testHttpDomain)) {
        serverHttpDomain = testHttpDomain;
    }
    #endif
    if (self.baseUrl) {
        return self.baseUrl;
    }
    return serverHttpDomain;
}

- (NSDictionary *)currentHeadersParams {
    if (self.headersParams) {
        return self.headersParams;
    }
    return nil;//@"固定的请求头";
}

- (NSTimeInterval)currentTimeOut {
    if (self.timeout > 0) {
        return self.timeout;
    }
    return 30.0f;
}

- (BOOL)currentIsFiletr {
    if (self.isFilter) {
        return self.isFilter;
    }
    return NO;
}
//解析返回结果
- (id)parseFormPesponseData:(id)responseData
{
    if ([responseData isKindOfClass:[NSData class]]) {
        // 尝试解析成JSON
        if (responseData == nil) {
            return responseData;
        } else {
            NSError *error = nil;
            NSDictionary *response = [NSJSONSerialization JSONObjectWithData:responseData
                                                                     options:NSJSONReadingMutableContainers
                                                                       error:&error];
            if (error != nil) {
                return responseData;
            } else {
                return response;
            }
        }
    }
    else {
        return responseData;
    }
}
@end
